﻿using System;
using Xss.Data.Sql;

namespace Xss.Data.Mapper
{
    public abstract class AdoMapper : IAdoMapper
    {

        public IAdoMapper Parent
        {
            get;
            set;
        }

        public IAdoMapper Next
        {
            get;
            set;
        }

        public ISqlProvider Sql
        {
            get;
            set;
        }

        public Type MapperType
        {
            get;
            set;
        }

        public virtual bool ParseParamater(object result)
        {
            Paramater = result;
            return true;
        }

        public bool IsValidRollback
        {
            get;
            set;
        }

        public IAdoRequest Request
        {
            get;
            set;
        }

        public void Dispose()
        {
            MapperType = null;
            Request = null;
            Parent = null;
            Next = null;
        }

        public object Paramater
        {
            get;
            set;
        }

        public object Execute()
        {
            RaisePreEvents();
            var exec = ExecuteIntenal(Paramater);
            RaisePostEvents();

            if (Next != null && ParseParamater(exec))
            {
                Next.Message = Message;
                return Next.Execute();
            }
            else if (IsValidRollback)
            {
                Message.ThrowException();
            }

            return exec;
        }

        void RaisePreEvents()
        {
            if (PreExecute != null)
                PreExecute.Invoke(this, new EventArgs());
        }

        void RaisePostEvents()
        {
            if (PoseExecute != null)
                PoseExecute.Invoke(this, new EventArgs());
        }

        protected abstract object ExecuteIntenal(object paramater);

        public event EventHandler<EventArgs> PreExecute;

        public event EventHandler<EventArgs> PoseExecute;


        public Message.MessageContext Message
        {
            get;
            set;
        }
    }
}
